﻿using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;

namespace ToDoListReminder.Data
{
	/// <summary>
	/// The application configuration data.
	/// </summary>
	[DataContract]
	public class Config : BaseDataObject
	{
		#region Fields

		/// <summary>
		/// Holds the project list.
		/// </summary>
		private ObservableCollection<Project> projects_;

		/// <summary>
		/// Holds the project list saved.
		/// </summary>
		private ObservableCollection<Project> projectsSaved_;
		#endregion

		#region Properties

		[DataMember]
		public ObservableCollection<Project> Projects
		{
			get
			{
				if (projects_ == null)
				{
					projects_ = new ObservableCollection<Project>();
				}

				return projects_;
			}
			set
			{
				projects_ = value; SetPropertyChanged("Projects");
			}
		}

		/// <summary>
		/// Gets or sets true, if the data was saved; otherwise false, if data was not saved.
		/// </summary>
		private bool IsDataSaved
		{
			get; set;
		}
		#endregion

		#region Constructors
		
		public Config()
		{
			IsDataSaved = false;
		}

		#endregion

		#region Methods
		
		/// <summary>
		/// Loads the configuration data.
		/// </summary>
		public void LoadData()
		{
			var fileName = GetFileName();

			if (File.Exists(fileName))
			{
				// Create serializer.
				var serializer = new DataContractSerializer(this.GetType());

				// Create reader
				var streamReader = new StreamReader(fileName);
				var xmlReader = XmlReader.Create(streamReader);

				// Deserialize
				var deserializedObject = (Config)serializer.ReadObject(xmlReader);
				xmlReader.Close();
				streamReader.Close();

				this.CancelEdit();
				this.Projects = deserializedObject.Projects;
			}

			IsDataSaved = false;
		}

		/// <summary>
		/// Saves the configuration data.
		/// </summary>
		public void SaveData()
		{
			if (!IsDataSaved)
			{
				var fileName = GetFileName();

				// Create serializer.
				var serializer = new DataContractSerializer(this.GetType());

				// Create writer
				var streamWriter = new StreamWriter(fileName);
				var xmlWriter = XmlWriter.Create(streamWriter);

				if (xmlWriter != null)
				{
					// Serialize.
					serializer.WriteObject(xmlWriter, this);
					xmlWriter.Flush();
					xmlWriter.Close();
					streamWriter.Close();
				}

				IsDataSaved = true;
			}
		}

		/// <summary>
		/// Gets the file name.
		/// </summary>
		/// <remarks>
		/// Creates the path to file, if necessarry.
		/// </remarks>
		/// <returns>The file name.</returns>
		private static string GetFileName()
		{
			var folderName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
			                                                               Assembly.GetExecutingAssembly().GetName().Name);
			if (!Directory.Exists(folderName))
			{
				Directory.CreateDirectory(folderName);
			}

			return Path.Combine(folderName, Assembly.GetExecutingAssembly().GetName().Name + ".config");
		}

		#endregion
		#region Overrides

		/// <summary>
		/// Saves the data members.
		/// </summary>
		protected override void Save()
		{
			projectsSaved_ = new ObservableCollection<Project>();
			foreach (var project in Projects)
			{
				project.BeginEdit();
				projectsSaved_.Add(project);
			}
		}

		/// <summary>
		/// Restores the data members.
		/// </summary>
		protected override void Restore()
		{
			foreach (var project in projectsSaved_)
			{
				project.CancelEdit();
			}

			Projects = projectsSaved_;
		}

		/// <summary>
		/// Gets the text representation of the instance.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			var buffer = new StringBuilder("Config:");

			buffer.Append(" Projects[");

			foreach (var project in Projects)
			{
				buffer.AppendFormat(", {0}", project.ToString());
			}
			buffer.Append("]");
			return buffer.ToString();
		}
		#endregion
	}
}
